#ifndef __DECISION_H__
#define __DECISION_H__

#include "../cursor/Cursor.hpp"
#include "../keyHanding/KeyHanding.hpp"
#include "../player/BlackPlayer.hpp"
#include "../player/Player.hpp"
#include "../player/WhitePlayer.hpp"
#include "Judge.hpp"
#include <functional>
#include <iostream>
#include <map>
#include <ostream>
#include <string>
#include <utility>
#include <vector>

/**
 * @brief 成功者
 *
 */
typedef enum { WHITE_WINNER = 0, BLACK_WINNER, EMPTY_WINNER } WINNER;

/**
 * @brief 决策类
 *
 */
class Decision {
private:
  Cursor *cursor;
  KeyHanding *key;
  CheckerBoard *checkerboard;
  Player *blackPlayer;
  Player *whitePlayer;
  Judge *judge;

  int playerList{0};

  std::map<KEYPRESS, std::function<void(void)>> funcMap;

public:
  Decision() : Decision("小黑", "小白") {}

  /**
   * @brief Construct a new Decision object
   *
   * @param blackPlayerName 黑棋
   * @param whitePlayerName 白棋
   */
  Decision(std::string blackPlayerName, std::string whitePlayerName) {
    cursor = new Cursor();
    key = new KeyHanding();
    checkerboard = CheckerBoard::getCheckerBoard();
    blackPlayer = new BlackPlayer(blackPlayerName);
    whitePlayer = new WhitePlayer(whitePlayerName);
    judge = new Judge();

    funcMap.insert(
        std::make_pair(KEYPRESS_W, std::bind(&Cursor::cursorUP, cursor)));
    funcMap.insert(
        std::make_pair(KEYPRESS_S, std::bind(&Cursor::cursorDown, cursor)));
    funcMap.insert(
        std::make_pair(KEYPRESS_A, std::bind(&Cursor::cursorLeft, cursor)));
    funcMap.insert(
        std::make_pair(KEYPRESS_D, std::bind(&Cursor::cursorRight, cursor)));

    checkerboard->checkerBoardShow();
    cursor->cursorShow();
  }

  ~Decision() {
    delete cursor;
    delete key;
    delete checkerboard;
    delete blackPlayer;
    delete whitePlayer;
    delete judge;
  }

  /**
   * @brief 决策函数
   *
   */
  void decisionGOGOGO() {
    KEYPRESS keyVal = KEYPRESS_EMPTY;
    WINNER winner = EMPTY_WINNER;

    while (1) {
      keyVal = key->KeyHandingVal();

      if (keyVal == KEYPRESS_Q) { // 退出
        break;
      } else if (keyVal == KEYPRESS_BLANK) { // 下棋
        winner = decisionPlayChess();
        if (winner == WHITE_WINNER) {
          checkerboard->checkerBoardShowWarning("白棋获胜！");
          break;
        } else if (winner == BLACK_WINNER) {
          checkerboard->checkerBoardShowWarning("黑棋获胜！");
          break;
        }
      } else { // 移动光标
        decisionMoveCursor(keyVal);
      }
    }
  }

  /**
   * @brief 下棋
   *
   */
  WINNER decisionPlayChess(void) {

    if ((++playerList) % 2 == 0) {
      if (!whitePlayer->playGames(cursor->getDisplayPositionX(),
                                  cursor->getDisplayPositionY())) {
        playerList--;
      } else {
        if (judge->judgeWinningAndLosing(cursor->getDisplayPositionX(),
                                         cursor->getDisplayPositionY())) {
          return WHITE_WINNER;
        }
      }
    } else {
      if (!blackPlayer->playGames(cursor->getDisplayPositionX(),
                                  cursor->getDisplayPositionY())) {
        playerList--;
      } else {
        if (judge->judgeWinningAndLosing(cursor->getDisplayPositionX(),
                                         cursor->getDisplayPositionY())) {
          return BLACK_WINNER;
        }
      }
    }
    return EMPTY_WINNER;
  }

  /**
   * @brief 移动光标
   *
   */
  void decisionMoveCursor(KEYPRESS keyVal) {

    auto it = funcMap.find(keyVal);
    if (it != funcMap.end()) {
      it->second(); // 执行 cursor->cursorXXX()
    } else {
      checkerboard->checkerBoardShowWarning("请按 W A S D 空格");
    }
  }
};

#endif // __DECISION_H__